Autogenerated HTML docs for v1.7.4 
diff --git a/git-bisect-lk2009.html b/git-bisect-lk2009.html index 9fcc46b..1cd5483 100644 --- a/git-bisect-lk2009.html +++ b/git-bisect-lk2009.html 
@@ -3,7 +3,8 @@  <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">   <head>   <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />  -<meta name="generator" content="AsciiDoc 8.2.5" />  +<meta name="generator" content="AsciiDoc 8.4.5" />  +<title>Fighting regressions with git bisect</title>   <style type="text/css">   /* Debug borders */   p, li, dt, dd, div, pre, h1, h2, h3, h4, h5, h6 {  @@ -26,10 +27,12 @@    em {   font-style: italic;  + color: navy;   }     strong {   font-weight: bold;  + color: #083194;   }     tt {  @@ -71,6 +74,10 @@  margin-bottom: 0.5em;   }    +ul, ol, li > p {  + margin-top: 0;  +}  +   pre {   padding: 0;   margin: 0;  @@ -84,7 +91,7 @@  }   span#email {   }  -span#revision {  +span#revnumber, span#revdate, span#revremark {   font-family: sans-serif;   }    @@ -104,11 +111,13 @@  padding-bottom: 0.5em;   }    -div#preamble,  +div#preamble {  + margin-top: 1.5em;  + margin-bottom: 1.5em;  +}   div.tableblock, div.imageblock, div.exampleblock, div.verseblock,   div.quoteblock, div.literalblock, div.listingblock, div.sidebarblock,   div.admonitionblock {  - margin-right: 10%;   margin-top: 1.5em;   margin-bottom: 1.5em;   }  @@ -123,6 +132,7 @@    /* Block element titles. */   div.title, caption.title {  + color: #527bbd;   font-family: sans-serif;   font-weight: bold;   text-align: left;  @@ -149,22 +159,33 @@  padding: 0.5em;   }    -div.listingblock {  - margin-right: 0%;  -}   div.listingblock > div.content {   border: 1px solid silver;   background: #f4f4f4;   padding: 0.5em;   }    -div.quoteblock > div.content {  +div.quoteblock {   padding-left: 2.0em;  + margin-right: 10%;   }  -  -div.attribution {  +div.quoteblock > div.attribution {  + padding-top: 0.5em;   text-align: right;   }  +  +div.verseblock {  + padding-left: 2.0em;  + margin-right: 10%;  +}  +div.verseblock > div.content {  + white-space: pre;  +}  +div.verseblock > div.attribution {  + padding-top: 0.75em;  + text-align: left;  +}  +/* DEPRECATED: Pre version 8.2.7 verse style literal block. */   div.verseblock + div.attribution {   text-align: left;   }  @@ -187,13 +208,9 @@  padding: 0.5em;   }    -div.verseblock div.content {  - white-space: pre;  -}  -   div.imageblock div.content { padding-left: 0; }  -div.imageblock img { border: 1px solid silver; }   span.image img { border-style: none; }  +a.image:visited { color: white; }     dl {   margin-top: 0.8em;  @@ -202,18 +219,38 @@  dt {   margin-top: 0.5em;   margin-bottom: 0;  - font-style: italic;  + font-style: normal;  + color: navy;   }   dd > *:first-child {  - margin-top: 0;  + margin-top: 0.1em;   }     ul, ol {   list-style-position: outside;   }  -div.olist2 ol {  +ol.arabic {  + list-style-type: decimal;  +}  +ol.loweralpha {   list-style-type: lower-alpha;   }  +ol.upperalpha {  + list-style-type: upper-alpha;  +}  +ol.lowerroman {  + list-style-type: lower-roman;  +}  +ol.upperroman {  + list-style-type: upper-roman;  +}  +  +div.compact ul, div.compact ol,  +div.compact p, div.compact p,  +div.compact div, div.compact div {  + margin-top: 0.1em;  + margin-bottom: 0.1em;  +}     div.tableblock > table {   border: 3px solid #527bbd;  @@ -225,22 +262,53 @@  tfoot {   font-weight: bold;   }  +td > div.verse {  + white-space: pre;  +}  +p.table {  + margin-top: 0;  +}  +/* Because the table frame attribute is overriden by CSS in most browsers. */  +div.tableblock > table[frame="void"] {  + border-style: none;  +}  +div.tableblock > table[frame="hsides"] {  + border-left-style: none;  + border-right-style: none;  +}  +div.tableblock > table[frame="vsides"] {  + border-top-style: none;  + border-bottom-style: none;  +}    -div.hlist {  +  +div.hdlist {   margin-top: 0.8em;   margin-bottom: 0.8em;   }  -div.hlist td {  - padding-bottom: 5px;  +div.hdlist tr {  + padding-bottom: 15px;   }  -td.hlist1 {  +dt.hdlist1.strong, td.hdlist1.strong {  + font-weight: bold;  +}  +td.hdlist1 {   vertical-align: top;  - font-style: italic;  + font-style: normal;   padding-right: 0.8em;  + color: navy;   }  -td.hlist2 {  +td.hdlist2 {   vertical-align: top;   }  +div.hdlist.compact tr {  + margin: 0;  + padding-bottom: 0;  +}  +  +.comment {  + background: yellow;  +}     @media print {   div#footer-badges { display: none; }  @@ -279,6 +347,7 @@  padding: 0.5em;   }   div.sidebar-title, div.image-title {  + color: #527bbd;   font-family: sans-serif;   font-weight: bold;   margin-top: 0.0em;  @@ -291,8 +360,17 @@  padding: 0.5em;   }    -div.quoteblock-content {  - padding-left: 2.0em;  +div.quoteblock-attribution {  + padding-top: 0.5em;  + text-align: right;  +}  +  +div.verseblock-content {  + white-space: pre;  +}  +div.verseblock-attribution {  + padding-top: 0.75em;  + text-align: left;   }     div.exampleblock-content {  @@ -303,18 +381,17 @@  /* IE6 sets dynamically generated links as visited. */   div#toc a:visited { color: blue; }   </style>  -<title>Fighting regressions with git bisect</title>   </head>   <body>   <div id="header">   <h1>Fighting regressions with git bisect</h1>   <span id="author">Christian Couder</span><br />   <span id="email"><tt>&lt;<a href="mailto:chriscool@tuxfamily.org">chriscool@tuxfamily.org</a>&gt;</tt></span><br />  -2009/11/08  +<span id="revdate">2009/11/08</span>   </div>   <h2 id="_abstract">Abstract</h2>   <div class="sectionbody">  -<div class="para"><p>"git bisect" enables software users and developers to easily find the  +<div class="paragraph"><p>"git bisect" enables software users and developers to easily find the   commit that introduced a regression. We show why it is important to   have good tools to fight regressions. We describe how "git bisect"   works from the outside and the algorithms it uses inside. Then we  @@ -324,42 +401,42 @@  </div>   <h2 id="_introduction_to_git_bisect">Introduction to "git bisect"</h2>   <div class="sectionbody">  -<div class="para"><p>Git is a Distributed Version Control system (DVCS) created by Linus  +<div class="paragraph"><p>Git is a Distributed Version Control system (DVCS) created by Linus   Torvalds and maintained by Junio Hamano.</p></div>  -<div class="para"><p>In Git like in many other Version Control Systems (VCS), the different  +<div class="paragraph"><p>In Git like in many other Version Control Systems (VCS), the different   states of the data that is managed by the system are called   commits. And, as VCS are mostly used to manage software source code,   sometimes "interesting" changes of behavior in the software are   introduced in some commits.</p></div>  -<div class="para"><p>In fact people are specially interested in commits that introduce a  +<div class="paragraph"><p>In fact people are specially interested in commits that introduce a   "bad" behavior, called a bug or a regression. They are interested in   these commits because a commit (hopefully) contains a very small set  -of source code changes. And it's much easier to understand and  +of source code changes. And it&#8217;s much easier to understand and   properly fix a problem when you only need to check a very small set of  -changes, than when you don't know where look in the first place.</p></div>  -<div class="para"><p>So to help people find commits that introduce a "bad" behavior, the  +changes, than when you don&#8217;t know where look in the first place.</p></div>  +<div class="paragraph"><p>So to help people find commits that introduce a "bad" behavior, the   "git bisect" set of commands was invented. And it follows of course   that in "git bisect" parlance, commits where the "interesting   behavior" is present are called "bad" commits, while other commits are   called "good" commits. And a commit that introduce the behavior we are   interested in is called a "first bad commit". Note that there could be   more than one "first bad commit" in the commit space we are searching.</p></div>  -<div class="para"><p>So "git bisect" is designed to help find a "first bad commit". And to  +<div class="paragraph"><p>So "git bisect" is designed to help find a "first bad commit". And to   be as efficient as possible, it tries to perform a binary search.</p></div>   </div>   <h2 id="_fighting_regressions_overview">Fighting regressions overview</h2>   <div class="sectionbody">   <h3 id="_regressions_a_big_problem">Regressions: a big problem</h3><div style="clear:left"></div>  -<div class="para"><p>Regressions are a big problem in the software industry. But it's  +<div class="paragraph"><p>Regressions are a big problem in the software industry. But it&#8217;s   difficult to put some real numbers behind that claim.</p></div>  -<div class="para"><p>There are some numbers about bugs in general, like a NIST study in  +<div class="paragraph"><p>There are some numbers about bugs in general, like a NIST study in   2002 <a href="#1">[1]</a> that said:</p></div>   <div class="quoteblock">   <div class="quoteblock-content">  -<div class="para"><p>Software bugs, or errors, are so prevalent and so detrimental that  +<div class="paragraph"><p>Software bugs, or errors, are so prevalent and so detrimental that   they cost the U.S. economy an estimated $59.5 billion annually, or   about 0.6 percent of the gross domestic product, according to a newly  -released study commissioned by the Department of Commerce's National  +released study commissioned by the Department of Commerce&#8217;s National   Institute of Standards and Technology (NIST). At the national level,   over half of the costs are borne by software users and the remainder   by software developers/vendors. The study also found that, although  @@ -371,82 +448,87 @@  to the development stages in which they are introduced. Currently,   over half of all errors are not found until "downstream" in the   development process or during post-sale software use.</p></div>  -<div class="attribution">  -</div></div></div>  -<div class="para"><p>And then:</p></div>  +</div>  +<div class="quoteblock-attribution">  +</div></div>  +<div class="paragraph"><p>And then:</p></div>   <div class="quoteblock">   <div class="quoteblock-content">  -<div class="para"><p>Software developers already spend approximately 80 percent of  +<div class="paragraph"><p>Software developers already spend approximately 80 percent of   development costs on identifying and correcting defects, and yet few   products of any type other than software are shipped with such high   levels of errors.</p></div>  -<div class="attribution">  -</div></div></div>  -<div class="para"><p>Eventually the conclusion started with:</p></div>  +</div>  +<div class="quoteblock-attribution">  +</div></div>  +<div class="paragraph"><p>Eventually the conclusion started with:</p></div>   <div class="quoteblock">   <div class="quoteblock-content">  -<div class="para"><p>The path to higher software quality is significantly improved software  +<div class="paragraph"><p>The path to higher software quality is significantly improved software   testing.</p></div>  -<div class="attribution">  -</div></div></div>  -<div class="para"><p>There are other estimates saying that 80% of the cost related to  +</div>  +<div class="quoteblock-attribution">  +</div></div>  +<div class="paragraph"><p>There are other estimates saying that 80% of the cost related to   software is about maintenance <a href="#2">[2]</a>.</p></div>  -<div class="para"><p>Though, according to Wikipedia <a href="#3">[3]</a>:</p></div>  +<div class="paragraph"><p>Though, according to Wikipedia <a href="#3">[3]</a>:</p></div>   <div class="quoteblock">   <div class="quoteblock-content">  -<div class="para"><p>A common perception of maintenance is that it is merely fixing  +<div class="paragraph"><p>A common perception of maintenance is that it is merely fixing   bugs. However, studies and surveys over the years have indicated that   the majority, over 80%, of the maintenance effort is used for   non-corrective actions (Pigosky 1997). This perception is perpetuated   by users submitting problem reports that in reality are functionality   enhancements to the system.</p></div>  -<div class="attribution">  -</div></div></div>  -<div class="para"><p>But we can guess that improving on existing software is very costly  +</div>  +<div class="quoteblock-attribution">  +</div></div>  +<div class="paragraph"><p>But we can guess that improving on existing software is very costly   because you have to watch out for regressions. At least this would   make the above studies consistent among themselves.</p></div>  -<div class="para"><p>Of course some kind of software is developed, then used during some  +<div class="paragraph"><p>Of course some kind of software is developed, then used during some   time without being improved on much, and then finally thrown away. In   this case, of course, regressions may not be a big problem. But on the   other hand, there is a lot of big software that is continually   developed and maintained during years or even tens of years by a lot   of people. And as there are often many people who depend (sometimes   critically) on such software, regressions are a really big problem.</p></div>  -<div class="para"><p>One such software is the linux kernel. And if we look at the linux  +<div class="paragraph"><p>One such software is the linux kernel. And if we look at the linux   kernel, we can see that a lot of time and effort is spent to fight   regressions. The release cycle start with a 2 weeks long merge   window. Then the first release candidate (rc) version is tagged. And   after that about 7 or 8 more rc versions will appear with around one   week between each of them, before the final release.</p></div>  -<div class="para"><p>The time between the first rc release and the final release is  +<div class="paragraph"><p>The time between the first rc release and the final release is   supposed to be used to test rc versions and fight bugs and especially   regressions. And this time is more than 80% of the release cycle   time. But this is not the end of the fight yet, as of course it   continues after the release.</p></div>  -<div class="para"><p>And then this is what Ingo Molnar (a well known linux kernel  +<div class="paragraph"><p>And then this is what Ingo Molnar (a well known linux kernel   developer) says about his use of git bisect:</p></div>   <div class="quoteblock">   <div class="quoteblock-content">  -<div class="para"><p>I most actively use it during the merge window (when a lot of trees  +<div class="paragraph"><p>I most actively use it during the merge window (when a lot of trees   get merged upstream and when the influx of bugs is the highest) - and   yes, there have been cases that i used it multiple times a day. My   average is roughly once a day.</p></div>  -<div class="attribution">  -</div></div></div>  -<div class="para"><p>So regressions are fought all the time by developers, and indeed it is  +</div>  +<div class="quoteblock-attribution">  +</div></div>  +<div class="paragraph"><p>So regressions are fought all the time by developers, and indeed it is   well known that bugs should be fixed as soon as possible, so as soon  -as they are found. That's why it is interesting to have good tools for  +as they are found. That&#8217;s why it is interesting to have good tools for   this purpose.</p></div>   <h3 id="_other_tools_to_fight_regressions">Other tools to fight regressions</h3><div style="clear:left"></div>  -<div class="para"><p>So what are the tools used to fight regressions? They are nearly the  +<div class="paragraph"><p>So what are the tools used to fight regressions? They are nearly the   same as those used to fight regular bugs. The only specific tools are   test suites and tools similar as "git bisect".</p></div>  -<div class="para"><p>Test suites are very nice. But when they are used alone, they are  +<div class="paragraph"><p>Test suites are very nice. But when they are used alone, they are   supposed to be used so that all the tests are checked after each   commit. This means that they are not very efficient, because many   tests are run for no interesting result, and they suffer from   combinational explosion.</p></div>  -<div class="para"><p>In fact the problem is that big software often has many different  +<div class="paragraph"><p>In fact the problem is that big software often has many different   configuration options and that each test case should pass for each   configuration after each commit. So if you have for each release: N   configurations, M commits and T test cases, you should perform:</p></div>  @@ -454,9 +536,9 @@  <div class="content">   <pre><tt>N * M * T tests</tt></pre>   </div></div>  -<div class="para"><p>where N, M and T are all growing with the size your software.</p></div>  -<div class="para"><p>So very soon it will not be possible to completely test everything.</p></div>  -<div class="para"><p>And if some bugs slip through your test suite, then you can add a test  +<div class="paragraph"><p>where N, M and T are all growing with the size your software.</p></div>  +<div class="paragraph"><p>So very soon it will not be possible to completely test everything.</p></div>  +<div class="paragraph"><p>And if some bugs slip through your test suite, then you can add a test   to your test suite. But if you want to use your new improved test   suite to find where the bug slipped in, then you will either have to   emulate a bisection process or you will perhaps bluntly test each  @@ -466,7 +548,7 @@  <h2 id="_git_bisect_overview">"git bisect" overview</h2>   <div class="sectionbody">   <h3 id="_starting_a_bisection">Starting a bisection</h3><div style="clear:left"></div>  -<div class="para"><p>The first "git bisect" subcommand to use is "git bisect start" to  +<div class="paragraph"><p>The first "git bisect" subcommand to use is "git bisect start" to   start the search. Then bounds must be set to limit the commit   space. This is done usually by giving one "bad" and at least one   "good" commit. They can be passed in the initial call to "git bisect  @@ -475,19 +557,19 @@  <div class="content">   <pre><tt>$ git bisect start [BAD [GOOD...]]</tt></pre>   </div></div>  -<div class="para"><p>or they can be set using:</p></div>  +<div class="paragraph"><p>or they can be set using:</p></div>   <div class="listingblock">   <div class="content">   <pre><tt>$ git bisect bad [COMMIT]</tt></pre>   </div></div>  -<div class="para"><p>and:</p></div>  +<div class="paragraph"><p>and:</p></div>   <div class="listingblock">   <div class="content">   <pre><tt>$ git bisect good [COMMIT...]</tt></pre>   </div></div>  -<div class="para"><p>where BAD, GOOD and COMMIT are all names that can be resolved to a  +<div class="paragraph"><p>where BAD, GOOD and COMMIT are all names that can be resolved to a   commit.</p></div>  -<div class="para"><p>Then "git bisect" will checkout a commit of its choosing and ask the  +<div class="paragraph"><p>Then "git bisect" will checkout a commit of its choosing and ask the   user to test it, like this:</p></div>   <div class="listingblock">   <div class="content">  @@ -495,17 +577,17 @@  Bisecting: 10928 revisions left to test after this (roughly 14 steps)   [2ec65f8b89ea003c27ff7723525a2ee335a2b393] x86: clean up using max_low_pfn on 32-bit</tt></pre>   </div></div>  -<div class="para"><p>Note that the example that we will use is really a toy example, we  +<div class="paragraph"><p>Note that the example that we will use is really a toy example, we   will be looking for the first commit that has a version like   "2.6.26-something", that is the commit that has a "SUBLEVEL = 26" line   in the top level Makefile. This is a toy example because there are   better ways to find this commit with git than using "git bisect" (for   example "git blame" or "git log -S&lt;string&gt;").</p></div>   <h3 id="_driving_a_bisection_manually">Driving a bisection manually</h3><div style="clear:left"></div>  -<div class="para"><p>At this point there are basically 2 ways to drive the search. It can  +<div class="paragraph"><p>At this point there are basically 2 ways to drive the search. It can   be driven manually by the user or it can be driven automatically by a   script or a command.</p></div>  -<div class="para"><p>If the user is driving it, then at each step of the search, the user  +<div class="paragraph"><p>If the user is driving it, then at each step of the search, the user   will have to test the current commit and say if it is "good" or "bad"   using the "git bisect good" or "git bisect bad" commands respectively   that have been described above. For example:</p></div>  @@ -515,7 +597,7 @@  Bisecting: 5480 revisions left to test after this (roughly 13 steps)   [66c0b394f08fd89236515c1c84485ea712a157be] KVM: kill file-&gt;f_count abuse in kvm</tt></pre>   </div></div>  -<div class="para"><p>And after a few more steps like that, "git bisect" will eventually  +<div class="paragraph"><p>And after a few more steps like that, "git bisect" will eventually   find a first bad commit:</p></div>   <div class="listingblock">   <div class="content">  @@ -529,7 +611,7 @@    :100644 100644 5cf8258195331a4dbdddff08b8d68642638eea57 4492984efc09ab72ff6219a7bc21fb6a957c4cd5 M Makefile</tt></pre>   </div></div>  -<div class="para"><p>At this point we can see what the commit does, check it out (if it's  +<div class="paragraph"><p>At this point we can see what the commit does, check it out (if it&#8217;s   not already checked out) or tinker with it, for example:</p></div>   <div class="listingblock">   <div class="content">  @@ -555,7 +637,7 @@    # *DOCUMENTATION*</tt></pre>   </div></div>  -<div class="para"><p>And when we are finished we can use "git bisect reset" to go back to  +<div class="paragraph"><p>And when we are finished we can use "git bisect reset" to go back to   the branch we were in before we started bisecting:</p></div>   <div class="listingblock">   <div class="content">  @@ -565,7 +647,7 @@  Switched to branch 'master'</tt></pre>   </div></div>   <h3 id="_driving_a_bisection_automatically">Driving a bisection automatically</h3><div style="clear:left"></div>  -<div class="para"><p>The other way to drive the bisection process is to tell "git bisect"  +<div class="paragraph"><p>The other way to drive the bisection process is to tell "git bisect"   to launch a script or command at each bisection step to know if the   current commit is "good" or "bad". To do that, we use the "git bisect   run" command. For example:</p></div>  @@ -599,37 +681,37 @@  :100644 100644 5cf8258195331a4dbdddff08b8d68642638eea57 4492984efc09ab72ff6219a7bc21fb6a957c4cd5 M Makefile   bisect run success</tt></pre>   </div></div>  -<div class="para"><p>In this example, we passed "grep <em>^SUBLEVEL = 25</em> Makefile" as  +<div class="paragraph"><p>In this example, we passed "grep <em>^SUBLEVEL = 25</em> Makefile" as   parameter to "git bisect run". This means that at each step, the grep   command we passed will be launched. And if it exits with code 0 (that   means success) then git bisect will mark the current state as   "good". If it exits with code 1 (or any code between 1 and 127   included, except the special code 125), then the current state will be   marked as "bad".</p></div>  -<div class="para"><p>Exit code between 128 and 255 are special to "git bisect run". They  +<div class="paragraph"><p>Exit code between 128 and 255 are special to "git bisect run". They   make it stop immediately the bisection process. This is useful for   example if the command passed takes too long to complete, because you   can kill it with a signal and it will stop the bisection process.</p></div>  -<div class="para"><p>It can also be useful in scripts passed to "git bisect run" to "exit  +<div class="paragraph"><p>It can also be useful in scripts passed to "git bisect run" to "exit   255" if some very abnormal situation is detected.</p></div>   <h3 id="_avoiding_untestable_commits">Avoiding untestable commits</h3><div style="clear:left"></div>  -<div class="para"><p>Sometimes it happens that the current state cannot be tested, for  +<div class="paragraph"><p>Sometimes it happens that the current state cannot be tested, for   example if it does not compile because there was a bug preventing it   at that time. This is what the special exit code 125 is for. It tells   "git bisect run" that the current commit should be marked as   untestable and that another one should be chosen and checked out.</p></div>  -<div class="para"><p>If the bisection process is driven manually, you can use "git bisect  +<div class="paragraph"><p>If the bisection process is driven manually, you can use "git bisect   skip" to do the same thing. (In fact the special exit code 125 makes   "git bisect run" use "git bisect skip" in the background.)</p></div>  -<div class="para"><p>Or if you want more control, you can inspect the current state using  +<div class="paragraph"><p>Or if you want more control, you can inspect the current state using   for example "git bisect visualize". It will launch gitk (or "git log"   if the DISPLAY environment variable is not set) to help you find a   better bisection point.</p></div>  -<div class="para"><p>Either way, if you have a string of untestable commits, it might  +<div class="paragraph"><p>Either way, if you have a string of untestable commits, it might   happen that the regression you are looking for has been introduced by  -one of these untestable commits. In this case it's not possible to  +one of these untestable commits. In this case it&#8217;s not possible to   tell for sure which commit introduced the regression.</p></div>  -<div class="para"><p>So if you used "git bisect skip" (or the run script exited with  +<div class="paragraph"><p>So if you used "git bisect skip" (or the run script exited with   special code 125) you could get a result like this:</p></div>   <div class="listingblock">   <div class="content">  @@ -642,13 +724,13 @@  We cannot bisect more!</tt></pre>   </div></div>   <h3 id="_saving_a_log_and_replaying_it">Saving a log and replaying it</h3><div style="clear:left"></div>  -<div class="para"><p>If you want to show other people your bisection process, you can get a  +<div class="paragraph"><p>If you want to show other people your bisection process, you can get a   log using for example:</p></div>   <div class="listingblock">   <div class="content">   <pre><tt>$ git bisect log &gt; bisect_log.txt</tt></pre>   </div></div>  -<div class="para"><p>And it is possible to replay it using:</p></div>  +<div class="paragraph"><p>And it is possible to replay it using:</p></div>   <div class="listingblock">   <div class="content">   <pre><tt>$ git bisect replay bisect_log.txt</tt></pre>  @@ -657,17 +739,17 @@  <h2 id="_git_bisect_details">"git bisect" details</h2>   <div class="sectionbody">   <h3 id="_bisection_algorithm">Bisection algorithm</h3><div style="clear:left"></div>  -<div class="para"><p>As the Git commits form a directed acyclic graph (DAG), finding the  +<div class="paragraph"><p>As the Git commits form a directed acyclic graph (DAG), finding the   best bisection commit to test at each step is not so simple. Anyway   Linus found and implemented a "truly stupid" algorithm, later improved   by Junio Hamano, that works quite well.</p></div>  -<div class="para"><p>So the algorithm used by "git bisect" to find the best bisection  +<div class="paragraph"><p>So the algorithm used by "git bisect" to find the best bisection   commit when there are no skipped commits is the following:</p></div>  -<div class="para"><p>1) keep only the commits that:</p></div>  -<div class="para"><p>a) are ancestor of the "bad" commit (including the "bad" commit itself),  +<div class="paragraph"><p>1) keep only the commits that:</p></div>  +<div class="paragraph"><p>a) are ancestor of the "bad" commit (including the "bad" commit itself),   b) are not ancestor of a "good" commit (excluding the "good" commits).</p></div>  -<div class="para"><p>This means that we get rid of the uninteresting commits in the DAG.</p></div>  -<div class="para"><p>For example if we start with a graph like this:</p></div>  +<div class="paragraph"><p>This means that we get rid of the uninteresting commits in the DAG.</p></div>  +<div class="paragraph"><p>For example if we start with a graph like this:</p></div>   <div class="listingblock">   <div class="content">   <pre><tt>G-Y-G-W-W-W-X-X-X-X  @@ -680,7 +762,7 @@    -&gt; time goes this way -&gt;</tt></pre>   </div></div>  -<div class="para"><p>where B is the "bad" commit, "G" are "good" commits and W, X, and Y  +<div class="paragraph"><p>where B is the "bad" commit, "G" are "good" commits and W, X, and Y   are other commits, we will get the following graph after this first   step:</p></div>   <div class="listingblock">  @@ -691,16 +773,16 @@  /   W---W</tt></pre>   </div></div>  -<div class="para"><p>So only the W and B commits will be kept. Because commits X and Y will  +<div class="paragraph"><p>So only the W and B commits will be kept. Because commits X and Y will   have been removed by rules a) and b) respectively, and because commits   G are removed by rule b) too.</p></div>  -<div class="para"><p>Note for git users, that it is equivalent as keeping only the commit  +<div class="paragraph"><p>Note for git users, that it is equivalent as keeping only the commit   given by:</p></div>   <div class="listingblock">   <div class="content">   <pre><tt>git rev-list BAD --not GOOD1 GOOD2...</tt></pre>   </div></div>  -<div class="para"><p>Also note that we don't require the commits that are kept to be  +<div class="paragraph"><p>Also note that we don&#8217;t require the commits that are kept to be   descendants of a "good" commit. So in the following example, commits W   and Z will be kept:</p></div>   <div class="listingblock">  @@ -709,9 +791,9 @@  /   Z-Z</tt></pre>   </div></div>  -<div class="para"><p>2) starting from the "good" ends of the graph, associate to each  +<div class="paragraph"><p>2) starting from the "good" ends of the graph, associate to each   commit the number of ancestors it has plus one</p></div>  -<div class="para"><p>For example with the following graph where H is the "bad" commit and A  +<div class="paragraph"><p>For example with the following graph where H is the "bad" commit and A   and D are some parents of some "good" commits:</p></div>   <div class="listingblock">   <div class="content">  @@ -721,7 +803,7 @@  /   D---E</tt></pre>   </div></div>  -<div class="para"><p>this will give:</p></div>  +<div class="paragraph"><p>this will give:</p></div>   <div class="listingblock">   <div class="content">   <pre><tt>1 2 3  @@ -731,10 +813,10 @@  1 2/   D---E</tt></pre>   </div></div>  -<div class="para"><p>3) associate to each commit: min(X, N - X)</p></div>  -<div class="para"><p>where X is the value associated to the commit in step 2) and N is the  +<div class="paragraph"><p>3) associate to each commit: min(X, N - X)</p></div>  +<div class="paragraph"><p>where X is the value associated to the commit in step 2) and N is the   total number of commits in the graph.</p></div>  -<div class="para"><p>In the above example we have N = 8, so this will give:</p></div>  +<div class="paragraph"><p>In the above example we have N = 8, so this will give:</p></div>   <div class="listingblock">   <div class="content">   <pre><tt>1 2 3  @@ -744,24 +826,24 @@  1 2/   D---E</tt></pre>   </div></div>  -<div class="para"><p>4) the best bisection point is the commit with the highest associated  +<div class="paragraph"><p>4) the best bisection point is the commit with the highest associated   number</p></div>  -<div class="para"><p>So in the above example the best bisection point is commit C.</p></div>  -<div class="para"><p>5) note that some shortcuts are implemented to speed up the algorithm</p></div>  -<div class="para"><p>As we know N from the beginning, we know that min(X, N - X) can't be  +<div class="paragraph"><p>So in the above example the best bisection point is commit C.</p></div>  +<div class="paragraph"><p>5) note that some shortcuts are implemented to speed up the algorithm</p></div>  +<div class="paragraph"><p>As we know N from the beginning, we know that min(X, N - X) can&#8217;t be   greater than N/2. So during steps 2) and 3), if we would associate N/2   to a commit, then we know this is the best bisection point. So in this   case we can just stop processing any other commit and return the   current commit.</p></div>   <h3 id="_bisection_algorithm_debugging">Bisection algorithm debugging</h3><div style="clear:left"></div>  -<div class="para"><p>For any commit graph, you can see the number associated with each  -commit using "git rev-list &#8212;bisect-all".</p></div>  -<div class="para"><p>For example, for the above graph, a command like:</p></div>  +<div class="paragraph"><p>For any commit graph, you can see the number associated with each  +commit using "git rev-list --bisect-all".</p></div>  +<div class="paragraph"><p>For example, for the above graph, a command like:</p></div>   <div class="listingblock">   <div class="content">   <pre><tt>$ git rev-list --bisect-all BAD --not GOOD1 GOOD2</tt></pre>   </div></div>  -<div class="para"><p>would output something like:</p></div>  +<div class="paragraph"><p>would output something like:</p></div>   <div class="listingblock">   <div class="content">   <pre><tt>e15b73ad3db9b48d7d1ade32f8cd23a751fe0ace (dist=3)  @@ -774,19 +856,19 @@  9e622a6dad403b71c40979743bb9d5be17b16bd6 (dist=0)</tt></pre>   </div></div>   <h3 id="_bisection_algorithm_discussed">Bisection algorithm discussed</h3><div style="clear:left"></div>  -<div class="para"><p>First let's define "best bisection point". We will say that a commit X  +<div class="paragraph"><p>First let&#8217;s define "best bisection point". We will say that a commit X   is a best bisection point or a best bisection commit if knowing its   state ("good" or "bad") gives as much information as possible whether   the state of the commit happens to be "good" or "bad".</p></div>  -<div class="para"><p>This means that the best bisection commits are the commits where the  +<div class="paragraph"><p>This means that the best bisection commits are the commits where the   following function is maximum:</p></div>   <div class="listingblock">   <div class="content">   <pre><tt>f(X) = min(information_if_good(X), information_if_bad(X))</tt></pre>   </div></div>  -<div class="para"><p>where information_if_good(X) is the information we get if X is good  +<div class="paragraph"><p>where information_if_good(X) is the information we get if X is good   and information_if_bad(X) is the information we get if X is bad.</p></div>  -<div class="para"><p>Now we will suppose that there is only one "first bad commit". This  +<div class="paragraph"><p>Now we will suppose that there is only one "first bad commit". This   means that all its descendants are "bad" and all the other commits are   "good". And we will suppose that all commits have an equal probability   of being good or bad, or of being the first bad commit, so knowing the  @@ -794,49 +876,49 @@  wherever these c commits are on the graph and whatever c is. (So we   suppose that these commits being for example on a branch or near a   good or a bad commit does not give more or less information).</p></div>  -<div class="para"><p>Let's also suppose that we have a cleaned up graph like one after step  +<div class="paragraph"><p>Let&#8217;s also suppose that we have a cleaned up graph like one after step   1) in the bisection algorithm above. This means that we can measure   the information we get in terms of number of commit we can remove from   the graph..</p></div>  -<div class="para"><p>And let's take a commit X in the graph.</p></div>  -<div class="para"><p>If X is found to be "good", then we know that its ancestors are all  +<div class="paragraph"><p>And let&#8217;s take a commit X in the graph.</p></div>  +<div class="paragraph"><p>If X is found to be "good", then we know that its ancestors are all   "good", so we want to say that:</p></div>   <div class="listingblock">   <div class="content">   <pre><tt>information_if_good(X) = number_of_ancestors(X) (TRUE)</tt></pre>   </div></div>  -<div class="para"><p>And this is true because at step 1) b) we remove the ancestors of the  +<div class="paragraph"><p>And this is true because at step 1) b) we remove the ancestors of the   "good" commits.</p></div>  -<div class="para"><p>If X is found to be "bad", then we know that its descendants are all  +<div class="paragraph"><p>If X is found to be "bad", then we know that its descendants are all   "bad", so we want to say that:</p></div>   <div class="listingblock">   <div class="content">   <pre><tt>information_if_bad(X) = number_of_descendants(X) (WRONG)</tt></pre>   </div></div>  -<div class="para"><p>But this is wrong because at step 1) a) we keep only the ancestors of  +<div class="paragraph"><p>But this is wrong because at step 1) a) we keep only the ancestors of   the bad commit. So we get more information when a commit is marked as   "bad", because we also know that the ancestors of the previous "bad"   commit that are not ancestors of the new "bad" commit are not the  -first bad commit. We don't know if they are good or bad, but we know  +first bad commit. We don&#8217;t know if they are good or bad, but we know   that they are not the first bad commit because they are not ancestor   of the new "bad" commit.</p></div>  -<div class="para"><p>So when a commit is marked as "bad" we know we can remove all the  +<div class="paragraph"><p>So when a commit is marked as "bad" we know we can remove all the   commits in the graph except those that are ancestors of the new "bad"   commit. This means that:</p></div>   <div class="listingblock">   <div class="content">   <pre><tt>information_if_bad(X) = N - number_of_ancestors(X) (TRUE)</tt></pre>   </div></div>  -<div class="para"><p>where N is the number of commits in the (cleaned up) graph.</p></div>  -<div class="para"><p>So in the end this means that to find the best bisection commits we  +<div class="paragraph"><p>where N is the number of commits in the (cleaned up) graph.</p></div>  +<div class="paragraph"><p>So in the end this means that to find the best bisection commits we   should maximize the function:</p></div>   <div class="listingblock">   <div class="content">   <pre><tt>f(X) = min(number_of_ancestors(X), N - number_of_ancestors(X))</tt></pre>   </div></div>  -<div class="para"><p>And this is nice because at step 2) we compute number_of_ancestors(X)  +<div class="paragraph"><p>And this is nice because at step 2) we compute number_of_ancestors(X)   and so at step 3) we compute f(X).</p></div>  -<div class="para"><p>Let's take the following graph as an example:</p></div>  +<div class="paragraph"><p>Let&#8217;s take the following graph as an example:</p></div>   <div class="listingblock">   <div class="content">   <pre><tt> G-H-I-J  @@ -845,12 +927,12 @@  \ /   K-L-M-N</tt></pre>   </div></div>  -<div class="para"><p>If we compute the following non optimal function on it:</p></div>  +<div class="paragraph"><p>If we compute the following non optimal function on it:</p></div>   <div class="listingblock">   <div class="content">   <pre><tt>g(X) = min(number_of_ancestors(X), number_of_descendants(X))</tt></pre>   </div></div>  -<div class="para"><p>we get:</p></div>  +<div class="paragraph"><p>we get:</p></div>   <div class="listingblock">   <div class="content">   <pre><tt> 4 3 2 1  @@ -861,7 +943,7 @@  K-L-M-N   4 3 2 1</tt></pre>   </div></div>  -<div class="para"><p>but with the algorithm used by git bisect we get:</p></div>  +<div class="paragraph"><p>but with the algorithm used by git bisect we get:</p></div>   <div class="listingblock">   <div class="content">   <pre><tt> 7 7 6 5  @@ -872,76 +954,76 @@  K-L-M-N   7 7 6 5</tt></pre>   </div></div>  -<div class="para"><p>So we chose G, H, K or L as the best bisection point, which is better  +<div class="paragraph"><p>So we chose G, H, K or L as the best bisection point, which is better   than F. Because if for example L is bad, then we will know not only   that L, M and N are bad but also that G, H, I and J are not the first   bad commit (since we suppose that there is only one first bad commit   and it must be an ancestor of L).</p></div>  -<div class="para"><p>So the current algorithm seems to be the best possible given what we  +<div class="paragraph"><p>So the current algorithm seems to be the best possible given what we   initially supposed.</p></div>   <h3 id="_skip_algorithm">Skip algorithm</h3><div style="clear:left"></div>  -<div class="para"><p>When some commits have been skipped (using "git bisect skip"), then  +<div class="paragraph"><p>When some commits have been skipped (using "git bisect skip"), then   the bisection algorithm is the same for step 1) to 3). But then we use   roughly the following steps:</p></div>  -<div class="para"><p>6) sort the commit by decreasing associated value</p></div>  -<div class="para"><p>7) if the first commit has not been skipped, we can return it and stop  +<div class="paragraph"><p>6) sort the commit by decreasing associated value</p></div>  +<div class="paragraph"><p>7) if the first commit has not been skipped, we can return it and stop   here</p></div>  -<div class="para"><p>8) otherwise filter out all the skipped commits in the sorted list</p></div>  -<div class="para"><p>9) use a pseudo random number generator (PRNG) to generate a random  +<div class="paragraph"><p>8) otherwise filter out all the skipped commits in the sorted list</p></div>  +<div class="paragraph"><p>9) use a pseudo random number generator (PRNG) to generate a random   number between 0 and 1</p></div>  -<div class="para"><p>10) multiply this random number with its square root to bias it toward  +<div class="paragraph"><p>10) multiply this random number with its square root to bias it toward   0</p></div>  -<div class="para"><p>11) multiply the result by the number of commits in the filtered list  +<div class="paragraph"><p>11) multiply the result by the number of commits in the filtered list   to get an index into this list</p></div>  -<div class="para"><p>12) return the commit at the computed index</p></div>  +<div class="paragraph"><p>12) return the commit at the computed index</p></div>   <h3 id="_skip_algorithm_discussed">Skip algorithm discussed</h3><div style="clear:left"></div>  -<div class="para"><p>After step 7) (in the skip algorithm), we could check if the second  +<div class="paragraph"><p>After step 7) (in the skip algorithm), we could check if the second   commit has been skipped and return it if it is not the case. And in   fact that was the algorithm we used from when "git bisect skip" was   developed in git version 1.5.4 (released on February 1st 2008) until   git version 1.6.4 (released July 29th 2009).</p></div>  -<div class="para"><p>But Ingo Molnar and H. Peter Anvin (another well known linux kernel  +<div class="paragraph"><p>But Ingo Molnar and H. Peter Anvin (another well known linux kernel   developer) both complained that sometimes the best bisection points   all happened to be in an area where all the commits are   untestable. And in this case the user was asked to test many   untestable commits, which could be very inefficient.</p></div>  -<div class="para"><p>Indeed untestable commits are often untestable because a breakage was  +<div class="paragraph"><p>Indeed untestable commits are often untestable because a breakage was   introduced at one time, and that breakage was fixed only after many   other commits were introduced.</p></div>  -<div class="para"><p>This breakage is of course most of the time unrelated to the breakage  +<div class="paragraph"><p>This breakage is of course most of the time unrelated to the breakage   we are trying to locate in the commit graph. But it prevents us to   know if the interesting "bad behavior" is present or not.</p></div>  -<div class="para"><p>So it is a fact that commits near an untestable commit have a high  +<div class="paragraph"><p>So it is a fact that commits near an untestable commit have a high   probability of being untestable themselves. And the best bisection   commits are often found together too (due to the bisection algorithm).</p></div>  -<div class="para"><p>This is why it is a bad idea to just chose the next best unskipped  +<div class="paragraph"><p>This is why it is a bad idea to just chose the next best unskipped   bisection commit when the first one has been skipped.</p></div>  -<div class="para"><p>We found that most commits on the graph may give quite a lot of  +<div class="paragraph"><p>We found that most commits on the graph may give quite a lot of   information when they are tested. And the commits that will not on   average give a lot of information are the one near the good and bad   commits.</p></div>  -<div class="para"><p>So using a PRNG with a bias to favor commits away from the good and  +<div class="paragraph"><p>So using a PRNG with a bias to favor commits away from the good and   bad commits looked like a good choice.</p></div>  -<div class="para"><p>One obvious improvement to this algorithm would be to look for a  +<div class="paragraph"><p>One obvious improvement to this algorithm would be to look for a   commit that has an associated value near the one of the best bisection   commit, and that is on another branch, before using the PRNG. Because   if such a commit exists, then it is not very likely to be untestable   too, so it will probably give more information than a nearly randomly   chosen one.</p></div>   <h3 id="_checking_merge_bases">Checking merge bases</h3><div style="clear:left"></div>  -<div class="para"><p>There is another tweak in the bisection algorithm that has not been  +<div class="paragraph"><p>There is another tweak in the bisection algorithm that has not been   described in the "bisection algorithm" above.</p></div>  -<div class="para"><p>We supposed in the previous examples that the "good" commits were  +<div class="paragraph"><p>We supposed in the previous examples that the "good" commits were   ancestors of the "bad" commit. But this is not a requirement of "git   bisect".</p></div>  -<div class="para"><p>Of course the "bad" commit cannot be an ancestor of a "good" commit,  +<div class="paragraph"><p>Of course the "bad" commit cannot be an ancestor of a "good" commit,   because the ancestors of the good commits are supposed to be   "good". And all the "good" commits must be related to the bad commit.   They cannot be on a branch that has no link with the branch of the   "bad" commit. But it is possible for a good commit to be related to a   bad commit and yet not be neither one of its ancestor nor one of its   descendants.</p></div>  -<div class="para"><p>For example, there can be a "main" branch, and a "dev" branch that was  +<div class="paragraph"><p>For example, there can be a "main" branch, and a "dev" branch that was   forked of the main branch at a commit named "D" like this:</p></div>   <div class="listingblock">   <div class="content">  @@ -949,29 +1031,29 @@  \   H-I-J &lt;--dev</tt></pre>   </div></div>  -<div class="para"><p>The commit "D" is called a "merge base" for branch "main" and "dev"  -because it's the best common ancestor for these branches for a merge.</p></div>  -<div class="para"><p>Now let's suppose that commit J is bad and commit G is good and that  +<div class="paragraph"><p>The commit "D" is called a "merge base" for branch "main" and "dev"  +because it&#8217;s the best common ancestor for these branches for a merge.</p></div>  +<div class="paragraph"><p>Now let&#8217;s suppose that commit J is bad and commit G is good and that   we apply the bisection algorithm like it has been previously   described.</p></div>  -<div class="para"><p>As described in step 1) b) of the bisection algorithm, we remove all  +<div class="paragraph"><p>As described in step 1) b) of the bisection algorithm, we remove all   the ancestors of the good commits because they are supposed to be good   too.</p></div>  -<div class="para"><p>So we would be left with only:</p></div>  +<div class="paragraph"><p>So we would be left with only:</p></div>   <div class="listingblock">   <div class="content">   <pre><tt>H-I-J</tt></pre>   </div></div>  -<div class="para"><p>But what happens if the first bad commit is "B" and if it has been  +<div class="paragraph"><p>But what happens if the first bad commit is "B" and if it has been   fixed in the "main" branch by commit "F"?</p></div>  -<div class="para"><p>The result of such a bisection would be that we would find that H is  -the first bad commit, when in fact it's B. So that would be wrong!</p></div>  -<div class="para"><p>And yes it can happen in practice that people working on one branch  +<div class="paragraph"><p>The result of such a bisection would be that we would find that H is  +the first bad commit, when in fact it&#8217;s B. So that would be wrong!</p></div>  +<div class="paragraph"><p>And yes it can happen in practice that people working on one branch   are not aware that people working on another branch fixed a bug! It   could also happen that F fixed more than one bug or that it is a   revert of some big development effort that was not ready to be   released.</p></div>  -<div class="para"><p>In fact development teams often maintain both a development branch and  +<div class="paragraph"><p>In fact development teams often maintain both a development branch and   a maintenance branch, and it would be quite easy for them if "git   bisect" just worked when they want to bisect a regression on the   development branch that is not on the maintenance branch. They should  @@ -980,21 +1062,21 @@  <div class="content">   <pre><tt>$ git bisect start dev main</tt></pre>   </div></div>  -<div class="para"><p>To enable that additional nice feature, when a bisection is started  +<div class="paragraph"><p>To enable that additional nice feature, when a bisection is started   and when some good commits are not ancestors of the bad commit, we   first compute the merge bases between the bad and the good commits and   we chose these merge bases as the first commits that will be checked   out and tested.</p></div>  -<div class="para"><p>If it happens that one merge base is bad, then the bisection process  +<div class="paragraph"><p>If it happens that one merge base is bad, then the bisection process   is stopped with a message like:</p></div>   <div class="listingblock">   <div class="content">   <pre><tt>The merge base BBBBBB is bad.   This means the bug has been fixed between BBBBBB and [GGGGGG,...].</tt></pre>   </div></div>  -<div class="para"><p>where BBBBBB is the sha1 hash of the bad merge base and [GGGGGG,&#8230;]  +<div class="paragraph"><p>where BBBBBB is the sha1 hash of the bad merge base and [GGGGGG,&#8230;]   is a comma separated list of the sha1 of the good commits.</p></div>  -<div class="para"><p>If some of the merge bases are skipped, then the bisection process  +<div class="paragraph"><p>If some of the merge bases are skipped, then the bisection process   continues, but the following message is printed for each skipped merge   base:</p></div>   <div class="listingblock">  @@ -1003,49 +1085,49 @@  So we cannot be sure the first bad commit is between MMMMMM and BBBBBB.   We continue anyway.</tt></pre>   </div></div>  -<div class="para"><p>where BBBBBB is the sha1 hash of the bad commit, MMMMMM is the sha1  +<div class="paragraph"><p>where BBBBBB is the sha1 hash of the bad commit, MMMMMM is the sha1   hash of the merge base that is skipped and [GGGGGG,&#8230;] is a comma   separated list of the sha1 of the good commits.</p></div>  -<div class="para"><p>So if there is no bad merge base, the bisection process continues as  +<div class="paragraph"><p>So if there is no bad merge base, the bisection process continues as   usual after this step.</p></div>   </div>   <h2 id="_best_bisecting_practices">Best bisecting practices</h2>   <div class="sectionbody">   <h3 id="_using_test_suites_and_git_bisect_together">Using test suites and git bisect together</h3><div style="clear:left"></div>  -<div class="para"><p>If you both have a test suite and use git bisect, then it becomes less  +<div class="paragraph"><p>If you both have a test suite and use git bisect, then it becomes less   important to check that all tests pass after each commit. Though of   course it is probably a good idea to have some checks to avoid   breaking too many things because it could make bisecting other bugs   more difficult.</p></div>  -<div class="para"><p>You can focus your efforts to check at a few points (for example rc  +<div class="paragraph"><p>You can focus your efforts to check at a few points (for example rc   and beta releases) that all the T test cases pass for all the N  -configurations. And when some tests don't pass you can use "git  +configurations. And when some tests don&#8217;t pass you can use "git   bisect" (or better "git bisect run"). So you should perform roughly:</p></div>   <div class="listingblock">   <div class="content">   <pre><tt>c * N * T + b * M * log2(M) tests</tt></pre>   </div></div>  -<div class="para"><p>where c is the number of rounds of test (so a small constant) and b is  +<div class="paragraph"><p>where c is the number of rounds of test (so a small constant) and b is   the ratio of bug per commit (hopefully a small constant too).</p></div>  -<div class="para"><p>So of course it's much better as it's O(N <strong> T) vs O(N </strong> T * M) if  +<div class="paragraph"><p>So of course it&#8217;s much better as it&#8217;s O(N * T) vs O(N * T * M) if   you would test everything after each commit.</p></div>  -<div class="para"><p>This means that test suites are good to prevent some bugs from being  +<div class="paragraph"><p>This means that test suites are good to prevent some bugs from being   committed and they are also quite good to tell you that you have some   bugs. But they are not so good to tell you where some bugs have been   introduced. To tell you that efficiently, git bisect is needed.</p></div>  -<div class="para"><p>The other nice thing with test suites, is that when you have one, you  +<div class="paragraph"><p>The other nice thing with test suites, is that when you have one, you   already know how to test for bad behavior. So you can use this   knowledge to create a new test case for "git bisect" when it appears   that there is a regression. So it will be easier to bisect the bug and   fix it. And then you can add the test case you just created to your   test suite.</p></div>  -<div class="para"><p>So if you know how to create test cases and how to bisect, you will be  +<div class="paragraph"><p>So if you know how to create test cases and how to bisect, you will be   subject to a virtuous circle:</p></div>  -<div class="para"><p>more tests =&gt; easier to create tests =&gt; easier to bisect =&gt; more tests</p></div>  -<div class="para"><p>So test suites and "git bisect" are complementary tools that are very  +<div class="paragraph"><p>more tests &#8658; easier to create tests &#8658; easier to bisect &#8658; more tests</p></div>  +<div class="paragraph"><p>So test suites and "git bisect" are complementary tools that are very   powerful and efficient when used together.</p></div>   <h3 id="_bisecting_build_failures">Bisecting build failures</h3><div style="clear:left"></div>  -<div class="para"><p>You can very easily automatically bisect broken builds using something  +<div class="paragraph"><p>You can very easily automatically bisect broken builds using something   like:</p></div>   <div class="listingblock">   <div class="content">  @@ -1053,17 +1135,17 @@  $ git bisect run make</tt></pre>   </div></div>   <h3 id="_passing_sh_c_some_commands_to_git_bisect_run">Passing sh -c "some commands" to "git bisect run"</h3><div style="clear:left"></div>  -<div class="para"><p>For example:</p></div>  +<div class="paragraph"><p>For example:</p></div>   <div class="listingblock">   <div class="content">   <pre><tt>$ git bisect run sh -c "make || exit 125; ./my_app | grep 'good output'"</tt></pre>   </div></div>  -<div class="para"><p>On the other hand if you do this often, then it can be worth having  +<div class="paragraph"><p>On the other hand if you do this often, then it can be worth having   scripts to avoid too much typing.</p></div>   <h3 id="_finding_performance_regressions">Finding performance regressions</h3><div style="clear:left"></div>  -<div class="para"><p>Here is an example script that comes slightly modified from a real  +<div class="paragraph"><p>Here is an example script that comes slightly modified from a real   world script used by Junio Hamano <a href="#4">[4]</a>.</p></div>  -<div class="para"><p>This script can be passed to "git bisect run" to find the commit that  +<div class="paragraph"><p>This script can be passed to "git bisect run" to find the commit that   introduced a performance regression:</p></div>   <div class="listingblock">   <div class="content">  @@ -1096,44 +1178,44 @@  fi</tt></pre>   </div></div>   <h3 id="_following_general_best_practices">Following general best practices</h3><div style="clear:left"></div>  -<div class="para"><p>It is obviously a good idea not to have commits with changes that  +<div class="paragraph"><p>It is obviously a good idea not to have commits with changes that   knowingly break things, even if some other commits later fix the   breakage.</p></div>  -<div class="para"><p>It is also a good idea when using any VCS to have only one small  +<div class="paragraph"><p>It is also a good idea when using any VCS to have only one small   logical change in each commit.</p></div>  -<div class="para"><p>The smaller the changes in your commit, the most effective "git  +<div class="paragraph"><p>The smaller the changes in your commit, the most effective "git   bisect" will be. And you will probably need "git bisect" less in the   first place, as small changes are easier to review even if they are   only reviewed by the committer.</p></div>  -<div class="para"><p>Another good idea is to have good commit messages. They can be very  +<div class="paragraph"><p>Another good idea is to have good commit messages. They can be very   helpful to understand why some changes were made.</p></div>  -<div class="para"><p>These general best practices are very helpful if you bisect often.</p></div>  +<div class="paragraph"><p>These general best practices are very helpful if you bisect often.</p></div>   <h3 id="_avoiding_bug_prone_merges">Avoiding bug prone merges</h3><div style="clear:left"></div>  -<div class="para"><p>First merges by themselves can introduce some regressions even when  +<div class="paragraph"><p>First merges by themselves can introduce some regressions even when   the merge needs no source code conflict resolution. This is because a   semantic change can happen in one branch while the other branch is not   aware of it.</p></div>  -<div class="para"><p>For example one branch can change the semantic of a function while the  +<div class="paragraph"><p>For example one branch can change the semantic of a function while the   other branch add more calls to the same function.</p></div>  -<div class="para"><p>This is made much worse if many files have to be fixed to resolve  -conflicts. That's why such merges are called "evil merges". They can  +<div class="paragraph"><p>This is made much worse if many files have to be fixed to resolve  +conflicts. That&#8217;s why such merges are called "evil merges". They can   make regressions very difficult to track down. It can even be   misleading to know the first bad commit if it happens to be such a   merge, because people might think that the bug comes from bad conflict   resolution when it comes from a semantic change in one branch.</p></div>  -<div class="para"><p>Anyway "git rebase" can be used to linearize history. This can be used  +<div class="paragraph"><p>Anyway "git rebase" can be used to linearize history. This can be used   either to avoid merging in the first place. Or it can be used to   bisect on a linear history instead of the non linear one, as this   should give more information in case of a semantic change in one   branch.</p></div>  -<div class="para"><p>Merges can be also made simpler by using smaller branches or by using  +<div class="paragraph"><p>Merges can be also made simpler by using smaller branches or by using   many topic branches instead of only long version related branches.</p></div>  -<div class="para"><p>And testing can be done more often in special integration branches  +<div class="paragraph"><p>And testing can be done more often in special integration branches   like linux-next for the linux kernel.</p></div>   <h3 id="_adapting_your_work_flow">Adapting your work-flow</h3><div style="clear:left"></div>  -<div class="para"><p>A special work-flow to process regressions can give great results.</p></div>  -<div class="para"><p>Here is an example of a work-flow used by Andreas Ericsson:</p></div>  -<div class="ilist"><ul>  +<div class="paragraph"><p>A special work-flow to process regressions can give great results.</p></div>  +<div class="paragraph"><p>Here is an example of a work-flow used by Andreas Ericsson:</p></div>  +<div class="ulist"><ul>   <li>   <p>   write, in the test suite, a test script that exposes the regression  @@ -1155,78 +1237,81 @@  </p>   </li>   </ul></div>  -<div class="para"><p>And here is what Andreas said about this work-flow <a href="#5">[5]</a>:</p></div>  +<div class="paragraph"><p>And here is what Andreas said about this work-flow <a href="#5">[5]</a>:</p></div>   <div class="quoteblock">   <div class="quoteblock-content">  -<div class="para"><p>To give some hard figures, we used to have an average report-to-fix  +<div class="paragraph"><p>To give some hard figures, we used to have an average report-to-fix   cycle of 142.6 hours (according to our somewhat weird bug-tracker  -which just measures wall-clock time). Since we moved to git, we've  +which just measures wall-clock time). Since we moved to git, we&#8217;ve   lowered that to 16.2 hours. Primarily because we can stay on top of  -the bug fixing now, and because everyone's jockeying to get to fix  -bugs (we're quite proud of how lazy we are to let git find the bugs  +the bug fixing now, and because everyone&#8217;s jockeying to get to fix  +bugs (we&#8217;re quite proud of how lazy we are to let git find the bugs   for us). Each new release results in ~40% fewer bugs (almost certainly   due to how we now feel about writing tests).</p></div>  -<div class="attribution">  -</div></div></div>  -<div class="para"><p>Clearly this work-flow uses the virtuous circle between test suites  +</div>  +<div class="quoteblock-attribution">  +</div></div>  +<div class="paragraph"><p>Clearly this work-flow uses the virtuous circle between test suites   and "git bisect". In fact it makes it the standard procedure to deal   with regression.</p></div>  -<div class="para"><p>In other messages Andreas says that they also use the "best practices"  +<div class="paragraph"><p>In other messages Andreas says that they also use the "best practices"   described above: small logical commits, topic branches, no evil   merge,&#8230; These practices all improve the bisectability of the commit   graph, by making it easier and more useful to bisect.</p></div>  -<div class="para"><p>So a good work-flow should be designed around the above points. That  +<div class="paragraph"><p>So a good work-flow should be designed around the above points. That   is making bisecting easier, more useful and standard.</p></div>   <h3 id="_involving_qa_people_and_if_possible_end_users">Involving QA people and if possible end users</h3><div style="clear:left"></div>  -<div class="para"><p>One nice about "git bisect" is that it is not only a developer  +<div class="paragraph"><p>One nice about "git bisect" is that it is not only a developer   tool. It can effectively be used by QA people or even end users (if   they have access to the source code or if they can get access to all   the builds).</p></div>  -<div class="para"><p>There was a discussion at one point on the linux kernel mailing list  +<div class="paragraph"><p>There was a discussion at one point on the linux kernel mailing list   of whether it was ok to always ask end user to bisect, and very good   points were made to support the point of view that it is ok.</p></div>  -<div class="para"><p>For example David Miller wrote <a href="#6">[6]</a>:</p></div>  +<div class="paragraph"><p>For example David Miller wrote <a href="#6">[6]</a>:</p></div>   <div class="quoteblock">   <div class="quoteblock-content">  -<div class="para"><p>What people don't get is that this is a situation where the "end node  +<div class="paragraph"><p>What people don&#8217;t get is that this is a situation where the "end node   principle" applies. When you have limited resources (here: developers)  -you don't push the bulk of the burden upon them. Instead you push  +you don&#8217;t push the bulk of the burden upon them. Instead you push   things out to the resource you have a lot of, the end nodes (here:   users), so that the situation actually scales.</p></div>  -<div class="attribution">  -</div></div></div>  -<div class="para"><p>This means that it is often "cheaper" if QA people or end users can do  +</div>  +<div class="quoteblock-attribution">  +</div></div>  +<div class="paragraph"><p>This means that it is often "cheaper" if QA people or end users can do   it.</p></div>  -<div class="para"><p>What is interesting too is that end users that are reporting bugs (or  +<div class="paragraph"><p>What is interesting too is that end users that are reporting bugs (or   QA people that reproduced a bug) have access to the environment where   the bug happens. So they can often more easily reproduce a   regression. And if they can bisect, then more information will be   extracted from the environment where the bug happens, which means that   it will be easier to understand and then fix the bug.</p></div>  -<div class="para"><p>For open source projects it can be a good way to get more useful  +<div class="paragraph"><p>For open source projects it can be a good way to get more useful   contributions from end users, and to introduce them to QA and   development activities.</p></div>   <h3 id="_using_complex_scripts">Using complex scripts</h3><div style="clear:left"></div>  -<div class="para"><p>In some cases like for kernel development it can be worth developing  +<div class="paragraph"><p>In some cases like for kernel development it can be worth developing   complex scripts to be able to fully automate bisecting.</p></div>  -<div class="para"><p>Here is what Ingo Molnar says about that <a href="#7">[7]</a>:</p></div>  +<div class="paragraph"><p>Here is what Ingo Molnar says about that <a href="#7">[7]</a>:</p></div>   <div class="quoteblock">   <div class="quoteblock-content">  -<div class="para"><p>i have a fully automated bootup-hang bisection script. It is based on  +<div class="paragraph"><p>i have a fully automated bootup-hang bisection script. It is based on   "git-bisect run". I run the script, it builds and boots kernels fully   automatically, and when the bootup fails (the script notices that via   the serial log, which it continuously watches - or via a timeout, if  -the system does not come up within 10 minutes it's a "bad" kernel),  +the system does not come up within 10 minutes it&#8217;s a "bad" kernel),   the script raises my attention via a beep and i power cycle the test   box. (yeah, i should make use of a managed power outlet to 100%   automate it)</p></div>  -<div class="attribution">  -</div></div></div>  +</div>  +<div class="quoteblock-attribution">  +</div></div>   <h3 id="_combining_test_suites_git_bisect_and_other_systems_together">Combining test suites, git bisect and other systems together</h3><div style="clear:left"></div>  -<div class="para"><p>We have seen that test suites an git bisect are very powerful when  +<div class="paragraph"><p>We have seen that test suites an git bisect are very powerful when   used together. It can be even more powerful if you can combine them   with other systems.</p></div>  -<div class="para"><p>For example some test suites could be run automatically at night with  +<div class="paragraph"><p>For example some test suites could be run automatically at night with   some unusual (or even random) configurations. And if a regression is   found by a test suite, then "git bisect" can be automatically   launched, and its result can be emailed to the author of the first bad  @@ -1236,51 +1321,51 @@  <h2 id="_the_future_of_bisecting">The future of bisecting</h2>   <div class="sectionbody">   <h3 id="_git_replace">"git replace"</h3><div style="clear:left"></div>  -<div class="para"><p>We saw earlier that "git bisect skip" is now using a PRNG to try to  +<div class="paragraph"><p>We saw earlier that "git bisect skip" is now using a PRNG to try to   avoid areas in the commit graph where commits are untestable. The   problem is that sometimes the first bad commit will be in an   untestable area.</p></div>  -<div class="para"><p>To simplify the discussion we will suppose that the untestable area is  +<div class="paragraph"><p>To simplify the discussion we will suppose that the untestable area is   a simple string of commits and that it was created by a breakage  -introduced by one commit (let's call it BBC for bisect breaking  -commit) and later fixed by another one (let's call it BFC for bisect  +introduced by one commit (let&#8217;s call it BBC for bisect breaking  +commit) and later fixed by another one (let&#8217;s call it BFC for bisect   fixing commit).</p></div>  -<div class="para"><p>For example:</p></div>  +<div class="paragraph"><p>For example:</p></div>   <div class="listingblock">   <div class="content">   <pre><tt>...-Y-BBC-X1-X2-X3-X4-X5-X6-BFC-Z-...</tt></pre>   </div></div>  -<div class="para"><p>where we know that Y is good and BFC is bad, and where BBC and X1 to  +<div class="paragraph"><p>where we know that Y is good and BFC is bad, and where BBC and X1 to   X6 are untestable.</p></div>  -<div class="para"><p>In this case if you are bisecting manually, what you can do is create  +<div class="paragraph"><p>In this case if you are bisecting manually, what you can do is create   a special branch that starts just before the BBC. The first commit in   this branch should be the BBC with the BFC squashed into it. And the   other commits in the branch should be the commits between BBC and BFC   rebased on the first commit of the branch and then the commit after   BFC also rebased on.</p></div>  -<div class="para"><p>For example:</p></div>  +<div class="paragraph"><p>For example:</p></div>   <div class="listingblock">   <div class="content">   <pre><tt> (BBC+BFC)-X1'-X2'-X3'-X4'-X5'-X6'-Z'   /   ...-Y-BBC-X1-X2-X3-X4-X5-X6-BFC-Z-...</tt></pre>   </div></div>  -<div class="para"><p>where commits quoted with ' have been rebased.</p></div>  -<div class="para"><p>You can easily create such a branch with Git using interactive rebase.</p></div>  -<div class="para"><p>For example using:</p></div>  +<div class="paragraph"><p>where commits quoted with ' have been rebased.</p></div>  +<div class="paragraph"><p>You can easily create such a branch with Git using interactive rebase.</p></div>  +<div class="paragraph"><p>For example using:</p></div>   <div class="listingblock">   <div class="content">   <pre><tt>$ git rebase -i Y Z</tt></pre>   </div></div>  -<div class="para"><p>and then moving BFC after BBC and squashing it.</p></div>  -<div class="para"><p>After that you can start bisecting as usual in the new branch and you  +<div class="paragraph"><p>and then moving BFC after BBC and squashing it.</p></div>  +<div class="paragraph"><p>After that you can start bisecting as usual in the new branch and you   should eventually find the first bad commit.</p></div>  -<div class="para"><p>For example:</p></div>  +<div class="paragraph"><p>For example:</p></div>   <div class="listingblock">   <div class="content">   <pre><tt>$ git bisect start Z' Y</tt></pre>   </div></div>  -<div class="para"><p>If you are using "git bisect run", you can use the same manual fix up  +<div class="paragraph"><p>If you are using "git bisect run", you can use the same manual fix up   as above, and then start another "git bisect run" in the special   branch. Or as the "git bisect" man page says, the script passed to   "git bisect run" can apply a patch before it compiles and test the  @@ -1289,57 +1374,57 @@  "git bisect" will be able to find the first bad commit. And the script   should not forget to remove the patch once the testing is done before   exiting from the script.</p></div>  -<div class="para"><p>(Note that instead of a patch you can use "git cherry-pick BFC" to  -apply the fix, and in this case you should use "git reset &#8212;hard  +<div class="paragraph"><p>(Note that instead of a patch you can use "git cherry-pick BFC" to  +apply the fix, and in this case you should use "git reset --hard   HEAD^" to revert the cherry-pick after testing and before returning   from the script.)</p></div>  -<div class="para"><p>But the above ways to work around untestable areas are a little bit  +<div class="paragraph"><p>But the above ways to work around untestable areas are a little bit   clunky. Using special branches is nice because these branches can be   shared by developers like usual branches, but the risk is that people   will get many such branches. And it disrupts the normal "git bisect"   work-flow. So, if you want to use "git bisect run" completely   automatically, you have to add special code in your script to restart   bisection in the special branches.</p></div>  -<div class="para"><p>Anyway one can notice in the above special branch example that the Z'  +<div class="paragraph"><p>Anyway one can notice in the above special branch example that the Z'   and Z commits should point to the same source code state (the same  -"tree" in git parlance). That's because Z' result from applying the  +"tree" in git parlance). That&#8217;s because Z' result from applying the   same changes as Z just in a slightly different order.</p></div>  -<div class="para"><p>So if we could just "replace" Z by Z' when we bisect, then we would  +<div class="paragraph"><p>So if we could just "replace" Z by Z' when we bisect, then we would   not need to add anything to a script. It would just work for anyone in   the project sharing the special branches and the replacements.</p></div>  -<div class="para"><p>With the example above that would give:</p></div>  +<div class="paragraph"><p>With the example above that would give:</p></div>   <div class="listingblock">   <div class="content">   <pre><tt> (BBC+BFC)-X1'-X2'-X3'-X4'-X5'-X6'-Z'-...   /   ...-Y-BBC-X1-X2-X3-X4-X5-X6-BFC-Z</tt></pre>   </div></div>  -<div class="para"><p>That's why the "git replace" command was created. Technically it  +<div class="paragraph"><p>That&#8217;s why the "git replace" command was created. Technically it   stores replacements "refs" in the "refs/replace/" hierarchy. These   "refs" are like branches (that are stored in "refs/heads/") or tags   (that are stored in "refs/tags"), and that means that they can   automatically be shared like branches or tags among developers.</p></div>  -<div class="para"><p>"git replace" is a very powerful mechanism. It can be used to fix  +<div class="paragraph"><p>"git replace" is a very powerful mechanism. It can be used to fix   commits in already released history, for example to change the commit   message or the author. And it can also be used instead of git "grafts"   to link a repository with another old repository.</p></div>  -<div class="para"><p>In fact it's this last feature that "sold" it to the git community, so  -it is now in the "master" branch of git's git repository and it should  +<div class="paragraph"><p>In fact it&#8217;s this last feature that "sold" it to the git community, so  +it is now in the "master" branch of git&#8217;s git repository and it should   be released in git 1.6.5 in October or November 2009.</p></div>  -<div class="para"><p>One problem with "git replace" is that currently it stores all the  +<div class="paragraph"><p>One problem with "git replace" is that currently it stores all the   replacements refs in "refs/replace/", but it would be perhaps better   if the replacement refs that are useful only for bisecting would be in   "refs/replace/bisect/". This way the replacement refs could be used   only for bisecting, while other refs directly in "refs/replace/" would   be used nearly all the time.</p></div>   <h3 id="_bisecting_sporadic_bugs">Bisecting sporadic bugs</h3><div style="clear:left"></div>  -<div class="para"><p>Another possible improvement to "git bisect" would be to optionally  +<div class="paragraph"><p>Another possible improvement to "git bisect" would be to optionally   add some redundancy to the tests performed so that it would be more   reliable when tracking sporadic bugs.</p></div>  -<div class="para"><p>This has been requested by some kernel developers because some bugs  +<div class="paragraph"><p>This has been requested by some kernel developers because some bugs   called sporadic bugs do not appear in all the kernel builds because   they are very dependent on the compiler output.</p></div>  -<div class="para"><p>The idea is that every 3 test for example, "git bisect" could ask the  +<div class="paragraph"><p>The idea is that every 3 test for example, "git bisect" could ask the   user to test a commit that has already been found to be "good" or   "bad" (because one of its descendants or one of its ancestors has been   found to be "good" or "bad" respectively). If it happens that a commit  @@ -1347,82 +1432,84 @@  aborted early, hopefully before too many mistakes have been made. Then   the user will have to look at what happened and then restart the   bisection using a fixed bisect log.</p></div>  -<div class="para"><p>There is already a project called BBChop created by Ealdwulf Wuffinga  +<div class="paragraph"><p>There is already a project called BBChop created by Ealdwulf Wuffinga   on Github that does something like that using Bayesian Search Theory   <a href="#9">[9]</a>:</p></div>   <div class="quoteblock">   <div class="quoteblock-content">  -<div class="para"><p>BBChop is like <em>git bisect</em> (or equivalent), but works when your bug  +<div class="paragraph"><p>BBChop is like <em>git bisect</em> (or equivalent), but works when your bug   is intermittent. That is, it works in the presence of false negatives   (when a version happens to work this time even though it contains the   bug). It assumes that there are no false positives (in principle, the   same approach would work, but adding it may be non-trivial).</p></div>  -<div class="attribution">  -</div></div></div>  -<div class="para"><p>But BBChop is independent of any VCS and it would be easier for Git  +</div>  +<div class="quoteblock-attribution">  +</div></div>  +<div class="paragraph"><p>But BBChop is independent of any VCS and it would be easier for Git   users to have something integrated in Git.</p></div>   </div>   <h2 id="_conclusion">Conclusion</h2>   <div class="sectionbody">  -<div class="para"><p>We have seen that regressions are an important problem, and that "git  +<div class="paragraph"><p>We have seen that regressions are an important problem, and that "git   bisect" has nice features that complement very well practices and   other tools, especially test suites, that are generally used to fight   regressions. But it might be needed to change some work-flows and   (bad) habits to get the most out of it.</p></div>  -<div class="para"><p>Some improvements to the algorithms inside "git bisect" are possible  +<div class="paragraph"><p>Some improvements to the algorithms inside "git bisect" are possible   and some new features could help in some cases, but overall "git   bisect" works already very well, is used a lot, and is already very  -useful. To back up that last claim, let's give the final word to Ingo  +useful. To back up that last claim, let&#8217;s give the final word to Ingo   Molnar when he was asked by the author how much time does he think   "git bisect" saves him when he uses it:</p></div>   <div class="quoteblock">   <div class="quoteblock-content">  -<div class="para"><p>a _lot_.</p></div>  -<div class="para"><p>About ten years ago did i do my first <em>bisection</em> of a Linux patch  +<div class="paragraph"><p>a <em>lot</em>.</p></div>  +<div class="paragraph"><p>About ten years ago did i do my first <em>bisection</em> of a Linux patch   queue. That was prior the Git (and even prior the BitKeeper) days. I   literally days spent sorting out patches, creating what in essence   were standalone commits that i guessed to be related to that bug.</p></div>  -<div class="para"><p>It was a tool of absolute last resort. I'd rather spend days looking  +<div class="paragraph"><p>It was a tool of absolute last resort. I&#8217;d rather spend days looking   at printk output than do a manual <em>patch bisection</em>.</p></div>  -<div class="para"><p>With Git bisect it's a breeze: in the best case i can get a ~15 step  +<div class="paragraph"><p>With Git bisect it&#8217;s a breeze: in the best case i can get a ~15 step   kernel bisection done in 20-30 minutes, in an automated way. Even with  -manual help or when bisecting multiple, overlapping bugs, it's rarely  +manual help or when bisecting multiple, overlapping bugs, it&#8217;s rarely   more than an hour.</p></div>  -<div class="para"><p>In fact it's invaluable because there are bugs i would never even  -_try_ to debug if it wasn't for git bisect. In the past there were bug  +<div class="paragraph"><p>In fact it&#8217;s invaluable because there are bugs i would never even  +<em>try</em> to debug if it wasn&#8217;t for git bisect. In the past there were bug   patterns that were immediately hopeless for me to debug - at best i   could send the crash/bug signature to lkml and hope that someone else   can think of something.</p></div>  -<div class="para"><p>And even if a bisection fails today it tells us something valuable  -about the bug: that it's non-deterministic - timing or kernel image  +<div class="paragraph"><p>And even if a bisection fails today it tells us something valuable  +about the bug: that it&#8217;s non-deterministic - timing or kernel image   layout dependent.</p></div>  -<div class="para"><p>So git bisect is unconditional goodness - and feel free to quote that  +<div class="paragraph"><p>So git bisect is unconditional goodness - and feel free to quote that   ;-)</p></div>  -<div class="attribution">  -</div></div></div>  +</div>  +<div class="quoteblock-attribution">  +</div></div>   </div>   <h2 id="_acknowledgements">Acknowledgements</h2>   <div class="sectionbody">  -<div class="para"><p>Many thanks to Junio Hamano for his help in reviewing this paper, for  +<div class="paragraph"><p>Many thanks to Junio Hamano for his help in reviewing this paper, for   reviewing the patches I sent to the git mailing list, for discussing   some ideas and helping me improve them, for improving "git bisect" a   lot and for his awesome work in maintaining and developing Git.</p></div>  -<div class="para"><p>Many thanks to Ingo Molnar for giving me very useful information that  +<div class="paragraph"><p>Many thanks to Ingo Molnar for giving me very useful information that   appears in this paper, for commenting on this paper, for his   suggestions to improve "git bisect" and for evangelizing "git bisect"   on the linux kernel mailing lists.</p></div>  -<div class="para"><p>Many thanks to Linus Torvalds for inventing, developing and  +<div class="paragraph"><p>Many thanks to Linus Torvalds for inventing, developing and   evangelizing "git bisect", Git and Linux.</p></div>  -<div class="para"><p>Many thanks to the many other great people who helped one way or  +<div class="paragraph"><p>Many thanks to the many other great people who helped one way or   another when I worked on git, especially to Andreas Ericsson, Johannes   Schindelin, H. Peter Anvin, Daniel Barkalow, Bill Lear, John Hawley,   Shawn O. Pierce, Jeff King, Sam Vilain, Jon Seymour.</p></div>  -<div class="para"><p>Many thanks to the Linux-Kongress program committee for choosing the  +<div class="paragraph"><p>Many thanks to the Linux-Kongress program committee for choosing the   author to given a talk and for publishing this paper.</p></div>   </div>   <h2 id="_references">References</h2>   <div class="sectionbody">  -<div class="ilist"><ul>  +<div class="ulist"><ul>   <li>   <p>   <a id="1"></a>[1] <a href="http://www.nist.gov/public_affairs/releases/n02-10.htm"><em>Software Errors Cost U.S. Economy $59.5 Billion Annually</em>. Nist News Release.</a>  @@ -1455,7 +1542,7 @@  </li>   <li>   <p>  -<a id="7"></a>[7] <a href="http://article.gmane.org/gmane.linux.scsi/36652/">Ingo Molnar. <em>Re: BUG 2.6.23-rc3 can't see sd partitions on Alpha</em>. Gmane.</a>  +<a id="7"></a>[7] <a href="http://article.gmane.org/gmane.linux.scsi/36652/">Ingo Molnar. <em>Re: BUG 2.6.23-rc3 can&#8217;t see sd partitions on Alpha</em>. Gmane.</a>   </p>   </li>   <li>  @@ -1472,7 +1559,7 @@  </div>   <div id="footer">   <div id="footer-text">  -Last updated 2010-09-18 23:57:08 UTC  +Last updated 2010-09-03 21:29:54 UTC   </div>   </div>   </body>